#pragma once

// 此文件中存放一些零碎的接口函数
#include <iostream>
#include <time.h>
#include <string>
#include <memory>
#include <vector>
#include <sstream>
#include <chrono>
#include <random>
#include <atomic>
#include <iomanip>
#include <jsoncpp/json/json.h>
using namespace std;
namespace bitrpc
{
#define LDBG 0        // 调试日志
#define LINF 1        // 信息提示日志
#define LERR 2        // 错误信息日志
#define LDEFAULT LDBG // 默认日志等级
// 这里的##VAARGS的作用是：
/*当宏被调用时，如DLOG(“%d-%s”, 90, “sai”)，##VAARGS会被替换为实际的参数列表(90, “sai”)
如果没有额外的参数（例如，只传递了格式字符串），##VAARGS会删除格式字符串后的逗号，避免产生语法错误*/
// format代表格式化字符串
#define LOG(level, format, ...)                                                              \
    {                                                                                        \
        if (level >= LDEFAULT)                                                               \
        {                                                                                    \
            time_t t = std::time(NULL);                                                        \
            struct tm *lt = localtime(&t);                                                   \
            char time_tmp[32] = {0};                                                         \
            strftime(time_tmp, 32, "%m-%d %T", lt);                                          \
            if (level == LDBG)                                                               \
                printf("[DEBUG LOG:");                                                        \
            else if (level == LINF)                                                          \
                printf("[INFO LOG:");                                                         \
            else                                                                             \
                printf("[ERROR LOG:");                                                        \
            printf("%s][%s:%d] " format "\n", time_tmp, __FILE__, __LINE__, ##__VA_ARGS__); \
        }                                                                                    \
    }
#define DLOG(format, ...) LOG(LDBG, format, ##__VA_ARGS__);
#define ILOG(format, ...) LOG(LINF, format, ##__VA_ARGS__);
#define ELOG(format, ...) LOG(LERR, format, ##__VA_ARGS__);

    class JSON
    {
    public:
        // 实现数据的json序列化,封装成一个函数，作用是将数据序列化成json字符串
        static bool Serialize(Json::Value &Student, string &outstr)
        {
            stringstream ss;
            Json::StreamWriterBuilder builder;
            builder["emitUTF8"] = true; // 设置UTF8编码
            unique_ptr<Json::StreamWriter> sw(builder.newStreamWriter());

            int n = sw->write(Student, &ss);
            if (n)
            {
                ELOG("Json Serialize Error");
                return false;
            }
            outstr = ss.str();
            return true;
        }
        // 实现json字符串的反序列化
        static bool Deserialize(string &jsonstr, Json::Value &Student)
        {
            // 先创建CharReader工厂类，用于创建具体的CharReader对象。
            Json::CharReaderBuilder builder;
            unique_ptr<Json::CharReader> reader(builder.newCharReader());
            string errs;
            bool ret = reader->parse(jsonstr.c_str(), jsonstr.c_str() + jsonstr.size(), &Student, &errs);
            if (ret == false)
            {
                ELOG(":Json Deserialize Error: %s", errs.c_str());
                return false;
            }
            return true;
        }
    };
    class UUID
    {
    public:
        static string uuid()
        {
            stringstream ss;
            // 1. 构造⼀个机器随机数对象
            std::random_device rd;

            // 2. 以机器随机数为种⼦构造伪随机数对象
            std::mt19937 generator(rd());
            // 3. 构造限定数据范围的对象
            std::uniform_int_distribution<int> distribution(0, 255); // 明确使用一字节存储
            // 4. ⽣成8个随机数，按照特定格式组织成为16进制数字字符的字符串
            for (int i = 0; i < 8; i++)
            {
                if (i == 4 || i == 6)
                    ss << "-";
                ss << setw(2) << setfill('0') << std::hex << distribution(generator);
            }
            ss << "-";
            // 5. 定义⼀个8字节序号，逐字节组织成为16进制数字字符的字符串
            static std::atomic<size_t> seq(1); // 00 00 00 00 00 00 00 01
            size_t cur = seq.fetch_add(1);
            for (int i = 7; i >= 0; i--)
            {
                if (i == 5)
                    ss << "-";
                ss << std::setw(2) << std::setfill('0') << std::hex << ((cur >> (i * 8)) & 0xFF);
            }
            return ss.str();
        }
    };
}
